package czolgisci.display;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;

import javax.swing.*;

import czolgisci.Engine;

/**
 * Okno gry. Inicjalizuje główną klasę gry Engine.
 * 
 * @author pillow
 * @pattern Singleton
 * @version 0.3
 */
public class GraphicInterface extends JFrame implements ActionListener
{
	private static GraphicInterface instance = null;

	private static final long serialVersionUID = 1L;
	private JPanel panel;
	private JTextField playerNames[];
	private HashMap<String, JLabel> livesFields;
	private int playersNumber;

	/**
	 * Metoda wzorca Singleton
	 * 
	 * @param title
	 *            tytuł okna
	 * @return jedyna instancja klasy
	 */
	static public GraphicInterface getInstance(String title, int playersNumber)
	{
		if (instance == null)
		{
			instance = new GraphicInterface(title, playersNumber);
		}
		return instance;
	}

	/**
	 * Prywatny konstruktor klasy
	 * 
	 * @param title
	 *            tytuł okna
	 * @param playersNumber
	 *            liczba graczy
	 */
	private GraphicInterface(String title, int playersNumber)  throws IllegalArgumentException
	{
		if (playersNumber < 2)
			throw new IllegalArgumentException("too small number of players (min 2)");

		this.playersNumber = playersNumber;
		playerNames = new JTextField[this.playersNumber];
		livesFields = new HashMap<String, JLabel>();

		setTitle(title);
		setSize(800, 600);
		setDefaultCloseOperation(GraphicInterface.EXIT_ON_CLOSE);
		setResizable(false);
		setLocation(100, 100);
		panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
		add(panel);

		drawSplash();
	}

	/**
	 * tworzy pole żyć dla danego gracza
	 * 
	 * @param playerName
	 * @param lifes
	 */
	public void createLifeField(String playerName, int lifes) throws IllegalArgumentException
	{
		if (lifes <= 0)
			throw new IllegalArgumentException("too small lifes number (must be greater than zero");

		JLabel newField = new JLabel(playerName + "[" + lifes + "]");
		livesFields.put(playerName, newField);
		panel.add(newField);
	}

	/**
	 * aktualizuje pole żyć danego gracza
	 * 
	 * @param playerName
	 * @param lifes
	 */
	public void updateLifeField(String playerName, int lifes)
	{
		if (lifes < 0)
			throw new IllegalArgumentException("too small lifes number (must be min 0");

		JLabel field = livesFields.get(playerName);
		field.setText(playerName + "[" + lifes + "]");
		livesFields.put(playerName, field);
	}

	/**
	 * wyswietla splash informujacy o zakończeniu gry, wskazuje zwycięzce
	 * 
	 * @param winnerName
	 */
	public void endGame(String winnerName)
	{
		panel.add(new JLabel("Wygrał: " + winnerName));
		setVisible(true);

		// tu ew. restart engine'u (ponowna gra) na zyczenie
	}

	/**
	 * Wyświetla splash początkowy z prośbą o podanie imion graczy
	 */
	private void drawSplash()
	{
		for (int i = 0; i < playersNumber; i++)
		{
			panel.add(new JLabel("Gracz " + (i + 1) + ":"));
			playerNames[i] = new JTextField(5);
			panel.add(playerNames[i]);
		}

		// TODO nie dałoby sie zrobić, żeby po enterze button też zaskakiwał? Na pewno są gotowe mechanizmy ;-)
		JButton button = new JButton("GO!");
		button.setActionCommand("Player names entered");
		button.addActionListener(this);
		panel.add(button);
		setVisible(true);
	}

	/**
	 * Inicjalizuje główną klasę gry Engine
	 */
	private void initGame()
	{
		String players[] = new String[playersNumber];
		int i = 0;

		for (JTextField name : playerNames)
		{
			players[i] = name.getText();
			i++;
		}

		// TODO jesli Engine jest juz zinicjalizowany, to tutaj powinny byc
		// bloki try..catch i powinny wchwytywać błędy
		// http://www.javalobby.org/articles/ultimate-image/#1 
		Engine.getInstance().init(this, (Graphics2D)panel.getRootPane().getGraphics(), players);
	}

	/**
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent e)
	{
		if ("Player names entered".equals(e.getActionCommand()))
		{
			// wylaczenie splasha
			panel.removeAll();
			panel.repaint();
			// zainicjowanie gry
			requestFocus();
			initGame();
		}
	}
}
